#include "uart.h"
#include <QDebug>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "color.h"
#include <QImage>
#include <QtGlobal>
#include <QTime>

#include "mainwindow.h"
#include "k8form.h"
#include "monitorform.h"
#include "k4form.h"
#include "hdform.h"
#include "vesaform.h"
#include "hdrform.h"
#include "hdcpform.h"
#include "patternform.h"
#include "audioform.h"
#include "sinkform.h"
#include "rootmenuform.h"
#include "signalinfoform.h"
#include "errorrateform.h"
#include "edidform.h"
#include "dscform.h"


//const int requestCmd[]={0xaa,0,0,06,0,0,0,timing_sel,0};
static int nPattern_index=0;
QImage *image;

QSerialPort serial;
QByteArray requestData;
k8Form *k8;
k4Form *k4;
hdForm *hd;
vesaForm *vesa;
hdrForm *hdr;
hdcpForm *hdcp;
patternForm *pattern;
audioForm *audio;
sinkForm *sink;
monitorForm *monitor;
MainWindow *mainwindow;
rootmenuForm *sgmenu;
signalinfoForm *signalinfo;
errorrateForm *errorrate;
edidForm *edid;
dscForm *dsc;
static int current_win=-1,preWin[8]={win_MAIN,win_MAIN,win_MAIN,win_MAIN,win_MAIN,win_MAIN,win_MAIN,win_MAIN};
static int currwin_pos=0,IsLastWinPre=0;
int ShowWin(int win_key,bool IsPreWin)
{
    int key=win_key;
    if(IsPreWin)
    {
        if(current_win==win_MAIN)
        {
            int i;
            currwin_pos=0;
            for(i=0;i<MAX_PreWin;i++)
                preWin[i]=win_MAIN;
            return 0;
        }
        currwin_pos=(currwin_pos-2+MAX_PreWin)%MAX_PreWin;
        if(IsLastWinPre++>=MAX_PreWin)
            key=win_MAIN;
        else
            key=preWin[currwin_pos];
        if(current_win==key)
            key=win_MAIN;
    }
    else
        IsLastWinPre=0;
//    qDebug()<<currwin_pos<<current_win<<key<<IsLastWinPre;
    if(current_win==key)
        return 0;
    switch(key)
    {
    case win_AUDIO:
        if(audio==NULL)
        audio=new audioForm();
        audio->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_SG:
        if(sgmenu==NULL)
        sgmenu=new rootmenuForm();
        sgmenu->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_4K:
        if(k4==NULL)
        k4=new k4Form();
        k4->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_HD:
        if(hd==NULL)
        hd=new hdForm();
        hd->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_8K:
        if(k8==NULL)
        k8=new k8Form();
        k8->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_VESA:
        if(vesa==NULL)
        vesa=new vesaForm();
        vesa->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_HDR:
        if(hdr==NULL)
        hdr=new hdrForm();
        hdr->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_HDCP:
        if(hdcp==NULL)
        hdcp=new hdcpForm();
        hdcp->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_PATTERN:
        if(pattern==NULL)
        pattern=new patternForm();
        pattern->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_SINKINFO:
        if(sink==NULL)
        sink=new sinkForm();sink->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_Signal_Info:
        if(signalinfo==NULL)
        signalinfo=new signalinfoForm();signalinfo->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_Error_Rate:
        if(errorrate==NULL)
        errorrate=new errorrateForm();errorrate->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_EDID:
        if(edid==NULL)
        edid=new edidForm();
        edid->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;
    case win_DSC:
        if(dsc==NULL)
        dsc=new dscForm();
        dsc->show();
        preWin[currwin_pos++]=key;
        if(currwin_pos==MAX_PreWin)
            currwin_pos=0;
        current_win=key;
        return 1;

    case Qt::Key_Exit:
    case Qt::Key_F10:
    case win_MAIN:
        if(mainwindow==NULL)
        mainwindow=new MainWindow();
        mainwindow->show();
        currwin_pos=0;
        preWin[currwin_pos++]=win_MAIN;
        current_win=win_MAIN;
        IsLastWinPre=0;
        return 1;
    }
    return 0;
};

int ShowPreWin()
{
   return ShowWin(0,true);
}

/*
QByteArray convertStringToCharArrary(QString qstrCmd)
{
//	QString qstrCmd = QString::fromStdString(strCmd);
    QByteArray chCmd;
    QStringList cmdList = qstrCmd.split(" ");
    int iSize = cmdList.size();
    qDebug()<<iSize;
    for (int i=0; i<iSize;i++)
    {
        QString s = cmdList.at(i);
        bool ok;
        int iHexnum = s.toInt(&ok, 16);
        chCmd[i] = iHexnum;
    }
    return chCmd;
}
*/
void get_checkum(void)
{
    int checksum=0,i;
    for(i=0;i<requestData.size()-1;i++)
    {
        checksum=requestData[i]+checksum;
    }
    checksum=~checksum+1;
    requestData[requestData.size()-1]=checksum;
}
void serial_init()
{
    serial.setBaudRate(115200,QSerialPort::AllDirections);
    serial.setParity(QSerialPort::NoParity);
    serial.setFlowControl(QSerialPort::NoFlowControl);
    serial.setDataBits(QSerialPort::Data8);//数据字节，8字节
    serial.setStopBits(QSerialPort::OneStop);//一位停止位
    serial.setPortName(COM_PORT);

    requestData.resize(11);
    requestData[0]=0xaa;
    requestData[1]=requestData[2]=requestData[4]=requestData[5]=requestData[6]=requestData[8]=0;
}

int sendUartCmd(int cmd,int param)
{
    bool datalenis2;int datalen=11;
    if(cmd==pattern_sel)
        datalen+=1;
    else if(cmd==set_link_training)
        datalen+=2;
    datalenis2=(cmd==pattern_sel||cmd==set_link_training);
    requestData.resize(datalen);
    requestData[3]=datalen-5;
    requestData[7]=cmd;
    requestData[8]=cmd>0xff?(cmd&0xff00)>>8:0;
    requestData[9]=param&0xff;
    if(datalen>=12)
        requestData[10]=(param&0xff00)>>8;
    if(datalen==13)
        requestData[11]=(param&0xff0000)>>16;

    return sendUart();
}

int sendUart(void)
{
    serial.close();

    if (!serial.open(QIODevice::ReadWrite))
    return -1;
    get_checkum();
       // write request
    qDebug()<<requestData;
    serial.write(requestData);

    if (serial.waitForBytesWritten(currentWaitTimeout))
            // read response
            if (serial.waitForReadyRead(currentWaitTimeout)) {
                QByteArray responseData = serial.readAll();
                while (serial.waitForReadyRead(10))
                    responseData += serial.readAll();
                qDebug()<<responseData;
            }
        serial.close();

     return 0;
}

int sendUartCmd_timing(int timing_code)
{
    return sendUartCmd(timing_sel,timing_code);
}
int sendUartCmd_pattern(int pattern_code)
{
    return sendUartCmd(pattern_sel,pattern_code);
}

bool SelectBox(QCheckBox **old_box,QCheckBox *new_box)
{
    if(*old_box!=NULL&&*old_box!=new_box)
    {
        (*old_box)->setBackgroundRole(QPalette::Highlight);
        (*old_box)->setChecked(false);
    }
    else
    {
        new_box->setBackgroundRole(QPalette::Highlight);
        new_box->setChecked(true);
    }
    *old_box=new_box;
    return true;
}
void SetPattern(int nPattern)
{
    nPattern_index=nPattern;
}
int GetPattern(void)
{
    return nPattern_index;
}

QImage *GetLogo()
{
    QImage *img=new QImage;
    img->load(LOGO_File);
    return img;
}
